Skip to content

Conversation

@DieterMai
Copy link

@DieterMai DieterMai commented Dec 29, 2025

The previous implementation had the following flaws:

  • On Linux, soft links to directories were followed, causing files outside the workspace to be deleted.
  • On Windows, the read-only flag was not removed explicitly. Before Java 25, this was done implicitly by the File.delete() method. Since Java 25, the flag must be removed before calling File.delete() or Files.delete(). See JDK-8355954.

This PR changes the implementation to:

  • Use the NIO file walker to iterate the root directory.
  • Avoid following symlinks.
  • Remove the Windows read-only flag explicitly.

Resolves #1958

@github-actions
Copy link

github-actions bot commented Dec 30, 2025

Test Results

   771 files  +  148     771 suites  +148   57m 42s ⏱️ + 2m 10s
 3 648 tests ±    0   3 594 ✅ +    2   54 💤 ± 0  0 ❌  - 2 
10 878 runs  +2 665  10 715 ✅ +2 643  163 💤 +24  0 ❌  - 2 

Results for commit 997190e. ± Comparison against base commit e8a7cec.

♻️ This comment has been updated with latest results.

@DieterMai
Copy link
Author

Note I tested this on Linux and Windows. No testing was done on MacOS

Copy link
Contributor

@merks merks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see there exists org.eclipse.osgi.storage.StorageUtil.rm(File, Debug) which also would suffer from the read-only problem, which is a problem I encounter with my SBOM work where I also have similar a utility:

https://github.com/eclipse-cbi/p2repo-sbom/blob/6a5d8b2f81a9db7a953df0b8d42cfeed80ab452a/plugins/org.eclipse.cbi.p2repo.sbom/src/org/eclipse/cbi/p2repo/sbom/IOUtil.java#L40C21-L40C27

Also this utility:

https://github.com/eclipse-cbi/p2repo-aggregator/blob/7cd178676200cc3c86457ce19bd373b764cd53bf/plugins/org.eclipse.cbi.p2repo.util/src/org/eclipse/cbi/p2repo/util/IOUtils.java#L83

This does this the old way:

org.eclipse.help.internal.search.SearchIndex.deleteDir(File)

The above is just an observation of how many places solve this problem with "duplicate" code...

// only use the root content for progress. anything else would
// be overkill.
long count = stream.count();
submonitor = SubMonitor.convert(monitor, (int) count);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic here is intricately tied to the if (Objects.equals(path.getParent(), root)) { guards in the walker. One might instead have specialized logic during preVisitDirectory for create a monitor only for the root.

In the end, this monitor will do a less good job of showing progress in a large branch. That makes me wonder if some kind of "stack" of monitors managed by preVisitDirectory/postVisitDirectory might not provide better progress? (Of course I'm not sure when/where such progress is displayed to the user, if anywhere.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the end, this monitor will do a less good job of showing progress in a large branch. That makes me wonder if some kind of "stack" of monitors managed by preVisitDirectory/postVisitDirectory might not provide better progress? (Of course I'm not sure when/where such progress is displayed to the user, if anywhere.)

I intentionally did id like this. I consider the progress monitoring here as very low priority. In my experience, the user does not care if 56% or 57% of the job is done. The progress bar is mostly used as an activity indicator that signals to the user that stuff is happening.
Using a stack of monitors would be more correct but also wrong since some directories are empty, other might by very big. In my opinion, it is a waist of time to optimize the progress monitoring.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I don't disagree about the value of the monitor. It's just an observation.

That being said, I had to go hunting in the code to understand how this monitor count related to how it's actually used in the code.

The previous implementation had the following flaws:

- On Linux, soft links to directories were followed, causing files
outside
the workspace to be deleted.
- On Windows, the read-only flag was not removed explicitly. Before Java
25, this was done implicitly by the File.delete() method. Since Java 25,
the flag must be removed before calling File.delete() or Files.delete().
See JDK-8355954.

This PR changes the implementation to:

- Use the NIO file walker to iterate the root directory.
- Avoid following symlinks.
- Remove the Windows read-only flag explicitly.

Signed-off-by: Dieter Mai <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CoreUtility.deleteContent() deletes files outside of the workspace

2 participants